<template>
  <div class="preview-mindmap-container" :style="{ width: `${canvasWidth}px`, height: `${canvasHeight}px`, backgroundColor: gloabConfig?.backgroundColor || backgroundColor }">
    <div id="map-container"></div>
    <WaterMark
      v-if="exportImage && gloabConfig?.watermark?.show"
      :backgroundColor="gloabConfig?.backgroundColor || backgroundColor"
      :content="gloabConfig?.watermark?.text" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import rough from 'roughjs'
import { useRoute } from 'vue-router'
import { select } from 'd3-selection'
import { apiGetMindMapJson } from '@/apis/mind'
import themes from '@/pages/mind-map/themes'
import skeleton from '@/pages/mind-map/skeleton'
import {
  createCanvasContainer,
  renderNewNodes,
  renderXmindOtherElement,
  renderNewEdges,
  drawXmindAuxiliaryElement,
  graphLengends
} from '@/pages/mind-map/graph'
import { generateNodeLinks } from '@/pages/mind-map/utils/layout'
import WaterMark from '@/pages/mind-map/components/WaterMark.vue'

let svg
let mindContainer
let rc
let displaySheet
let skeletonTheme
const [canvasWidth, canvasHeight] = [ref(576), ref(360)]
const spacing = 36

const route = useRoute()

const mindId = route.params.mindId
const mapId = route.params.mapId
const exportImage = Boolean(route.query.export)

const backgroundColor = ref('')

const gloabConfig = ref(null)

/**
 * 查询导图内指定画布的mapJson数据
 */
const queryTargetMindMapJson = async () => {
  const data = await apiGetMindMapJson({ mindId, mapId })
  displaySheet = data
  gloabConfig.value = displaySheet.gloabConfig
  initXmindContainer('map-container', data)
  handleRemoveAllElementEvents()
}
queryTargetMindMapJson()

const initXmindContainer = (id) => {
  const ele = document.getElementById(id)
  svg = select(ele).append('svg').attr('id', 'preview-xmind-map-svg')
    .attr('width', ele.clientWidth).attr('height', ele.clientHeight)
    .attr('xmlns', 'http://www.w3.org/2000/svg')
    .attr('xmlns:xlink', 'http://www.w3.org/1999/xlink')
  mindContainer = svg.append('g').attr('class', 'map-outter-container').attr('transform-origin', ' 50% 50%')
  handleRenderMindMap()
}

const handleRenderMindMap = () => {
  getSkeletonTheme()
  rc = rough.svg(mindContainer)
  createCanvasContainer(svg, rc)
  drawXmindAuxiliaryElement(skeletonTheme)
  const { compact, aligning } = displaySheet.gloabConfig
  const { nodes = [], edges = [], relationNodes = [] } = generateNodeLinks(displaySheet.rootTopic, skeletonTheme, compact, aligning)
  renderNewNodes(nodes, skeletonTheme)
  renderNewEdges(edges)
  renderXmindOtherElement(undefined, relationNodes, skeletonTheme)
  graphLengends(displaySheet.lengend, displaySheet.rootTopic)
}

/**
 * 导图主题和结构数据获取
 */
const getSkeletonTheme = () => {
  const skeletonSplit = displaySheet.skeleton.split('-')
  const themeSplit = displaySheet.theme.split('-')
  const cskeleton = skeleton[skeletonSplit[0]][skeletonSplit[1]]
  skeletonTheme = cskeleton[skeletonSplit[1]]({
    ...themes[themeSplit[0]][themeSplit[1]],
    ...themes[themeSplit[0]][themeSplit[1]][cskeleton.themeStyle]
  })
  backgroundColor.value = skeletonTheme.backgroundColor
  sessionStorage.setItem('isRough', skeletonTheme.nodeRoughOptions ? '1' : '0')
}

/**
 * 所有画布元素事件移除
 * 画布大小更新
 */
const handleRemoveAllElementEvents = () => {
  const { width: cwidth, height: cheight, top: ctop, bottom: cbottom, left: cleft, right: cright } = select('#preview-xmind-map-svg .map-outter-container').node().getBoundingClientRect()
  const { width, height, left, top } = select('#preview-xmind-map-svg .map-outter-container .x-mind-root-theme').node().getBoundingClientRect()
  // 如果当前预览界面为导图1:1图片，则画布不做缩放处理
  if (exportImage) {
    canvasWidth.value = cwidth
    canvasHeight.value = cheight
    svg.attr('width', cwidth).attr('height', cheight)
  }
  const scalex = Math.min((canvasWidth.value - spacing * 2) / cwidth, (canvasHeight.value - spacing * 2) / cheight)
  const scaley = Math.min((canvasWidth.value - spacing * 2) / cwidth, (canvasHeight.value - spacing * 2) / cheight)
  const x1 = width / 2 + left - cleft
  const x2 = cright - (width / 2 + left)
  const y1 = height / 2 + top - ctop
  const y2 = cbottom - (height / 2 + top)
  mindContainer
    .attr('transform', `scale(${Math.min(scalex, scaley)}) translate(${(canvasWidth.value - width) / 2 - (x2 - x1) / 2}, ${(canvasHeight.value - height) / 2 - (y2 - y1) / 2})`)
    .selectAll('g, path, rect, circle, div, p')
    .attr('class', null)
    .attr('id', null)
    .on('click', null)
    .on('mousedown', null)
    .on('mousemove', null)
    .on('mouseleave', null)
    .on('mouseup', null)
    .on('mouseover', null)
    .on('mouseenter', null)
}
</script>

<style lang="scss" scoped>
.preview-mindmap-container {
  position: relative;
  #map-container {
    width: 100%;
    height: 100%;
  }
}
</style>
